package org.xx.armory.service.security;

import org.xx.armory.security.Role;
import org.xx.armory.security.User;

import java.util.List;
import java.util.Optional;

/**
 * 帐户角色管理服务接口。
 *
 * <p>
 * <strong>用户名和角色名都不区分大小写。</strong>
 * </p>
 *
 * @author Haart
 */
public interface UserPermProvider {
    /**
     * 检查用户名和密码是否匹配。
     *
     * @param userName
     *         用户名, 正规化处理。
     * @param password
     *         密码, 正规化处理。
     * @return 如果存在用户名和密码匹配的记录则返回{@code true}, 否则返回{@code false}。
     */
    boolean validateUser(
            String userName,
            String password
    );

    /**
     * 根据用户名获取用户记录。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @return 用户记录, 如果不存在则返回{@code null}。
     * @throws NullPointerException
     *         如果参数{@code userName}是{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code userName}只包含空白字符。
     */
    Optional<User> loadUserByName(String userName);

    /**
     * 根据角色名获取角色记录。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @return 角色记录, 如果不存在则返回{@code null}。
     * @throws NullPointerException
     *         如果参数{@code userName}是{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code userName}只包含空白字符。
     */
    Optional<Role> loadRoleByName(String roleName);

    /**
     * 查找符合条件的用户记录。
     *
     * @param keyword
     *         关键字, 用于部分匹配用户名和属性, 会被正规化, 如果是{@code null}或者空白字符则忽略此条件。
     * @param roleName
     *         角色名，如果是{@code null}或者只包含空白字符则忽略此条件。
     * @param enabled
     *         是否启用, 如果是{@code null}则忽略此条件。
     * @param startRowIndex
     *         第一条记录的序号(从{@code 0}开始)。
     * @param maximumRows
     *         最多返回的记录数。
     * @return 符合条件的记录列表, 如果没有符合条件的记录则返回空列表。
     * @see #findUsersCount(String, String, Boolean)
     */
    List<User> findUsers(
            String keyword,
            String roleName,
            Boolean enabled,
            int startRowIndex,
            int maximumRows
    );

    /**
     * 查找符合条件的用户记录数。
     *
     * @param keyword
     *         关键字, 用于部分匹配用户名和属性, 会被正规化, 如果是{@code null}或者空白字符则忽略此条件。
     * @param roleName
     *         角色名，如果是{@code null}或者只包含空白字符则忽略此条件。
     * @param enabled
     *         是否启用, 如果是{@code null}则忽略此条件。
     * @return 符合条件的用户记录数。
     * @see #findUsers(String, String, Boolean, int, int)
     */
    int findUsersCount(
            String keyword,
            String roleName,
            Boolean enabled
    );

    /**
     * 查询所有用户的列表。
     *
     * @return 所有用户的列表。
     */
    List<User> findAllUsers();

    /**
     * 查找符合条件的角色记录。
     *
     * @param keyword
     *         关键字, 用于部分匹配角色名或角色显示名或角色描述, 会被正规化, 如果是{@code null}或者空白字符则忽略此条件。
     * @param enabled
     *         是否启用, 如果是{@code null}则忽略此条件。
     * @param startRowIndex
     *         第一条记录的序号(从{@code 0}开始)。
     * @param maximumRows
     *         最多返回的记录数。
     * @return 符合条件的记录列表, 如果没有符合条件的记录则返回空列表。
     */
    List<Role> findRoles(
            String keyword,
            Boolean enabled,
            int startRowIndex,
            int maximumRows
    );

    /**
     * 查找符合条件的角色记录。
     *
     * @param keyword
     *         关键字, 用于部分匹配角色名或角色显示名或角色描述, 会被正规化, 如果是{@code null}或者空白字符则忽略此条件。
     * @param enabled
     *         是否启用, 如果是{@code null}则忽略此条件。
     * @return 符合条件的记录数。
     */
    int findRolesCount(
            String keyword,
            Boolean enabled
    );

    /**
     * 查询指定用户具有的角色列表。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @return 此用户具有的角色列表, 如果指定用户名为{@code null}或者只包含空白字符则返回空列表。
     */
    List<String> findRolesByUser(String userName);

    /**
     * 根据角色名称查询所有具有指定角色的用户名列表。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @return 具有指定角色的所有用户名, 如果指定角色名为{@code null}或者只包含空白字符则返回空列表。
     */
    List<String> findUsersByRole(String roleName);

    /**
     * 根据角色名查询此角色所有的权限。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @return 指定角色的所有权限, 如果指定角色名为{@code null}或者只包含空白字符则返回空列表。
     */
    List<Long> findPermsByRole(String roleName);

    /**
     * 判断指定的用户是否具有指定的权限。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @param roleName
     *         角色名, 会被正规化。
     * @return 如果指定的用户具有指定的权限则返回{@code true}, 否则返回{@code false}, 如果{@code userName}是{@code null}
     * 或者只包含空白字符则返回{@code false}, 如果{@code roleName}是{@code null}或者只包含空白字符也返回{@code false}。
     */
    boolean isUserInRole(
            String userName,
            String roleName
    );

    /**
     * 判断指定的帐户是否具有指定的任意权限。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @param permissions
     *         权限数组
     * @return 如果用户具有指定的任意权限则返回{@code true}，否则返回{@code false}，如果
     * {@code permissions == null || permissions.length == 0}则返回{@code false}。
     */
    boolean isPermitted(
            String userName,
            int[] permissions
    );

    /**
     * 判断指定的用户是否存在。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @return 如果指定的用户存在则返回{@code true}, 否则返回{@code false}。
     */
    boolean isUserExists(String userName);

    /**
     * 判断指定的角色是否存在。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @return 如果指定的角色存在则返回{@code true}, 否则返回{@code false}。
     */
    boolean isRoleExists(String roleName);

    /**
     * 添加一个新用户。
     *
     * @param user
     *         用户记录。
     * @return 新添加的用户的用户名。
     * @throws NullPointerException
     *         如果参数{@code user}是{@code null}。
     */
    String addUser(User user);

    /**
     * 删除一个已存在的用户。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @return 成功删除的记录数。
     */
    int removeUser(String userName);

    /**
     * 更新一个已存在的用户。
     *
     * @param user
     *         用户记录。
     * @return 成功更新的记录数。
     * @throws NullPointerException
     *         如果参数{@code user}是{@code null}。
     */
    int updateUser(User user);

    /**
     * 更新密码。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @param newPassword
     *         新密码, 会被正规化。
     * @return 成功更新密码的记录数。
     */
    int updatePassword(
            String userName,
            String newPassword
    );

    /**
     * 添加角色。
     *
     * @param role
     *         角色记录。
     * @return 新添加的角色的记录数。
     * @throws NullPointerException
     *         如果参数{@code role}是{@code null}。
     */
    int addRole(Role role);

    /**
     * 删除已存在的角色。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @return 成功删除的记录数。
     */
    int removeRole(String roleName);

    /**
     * 更新已存在的角色。
     *
     * @param role
     *         角色记录。
     * @return 成功更新的记录数。
     * @throws NullPointerException
     *         如果参数{@code role}是{@code null}。
     */
    int updateRole(Role role);

    /**
     * 重置密码。
     *
     * @param userName
     *         用户名, 会被正规化。
     * @return 成功重置密码的用户名。
     */
    String resetPassword(String userName);

    /**
     * 分配角色。
     *
     * <p>
     * 此用户原有的角色会被删除。
     * </p>
     *
     * @param userName
     *         用户名, 会被正规化。
     * @param roleNames
     *         分配给此用户的角色。
     * @return 成功分配角色的用户数。
     * @throws NullPointerException
     *         如果参数{@code userName}是{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code userName}只包含空白字符。
     */
    int assignRoles(
            String userName,
            String... roleNames
    );

    /**
     * 分配权限。
     *
     * @param roleName
     *         角色名, 会被正规化。
     * @param permissions
     *         分配给此角色的权限。
     * @return 成功分配权限的角色数。
     * @throws NullPointerException
     *         如果参数{@code roleName}是{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code roleName}只包含空白字符。
     */
    int assignPerms(
            String roleName,
            long... permissions
    );
}
